/**
 * 
 */
package spl.manager;

import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import spl.manager.JobsContainer.Job;

/**
 * HTMLRenderer provides an abstraction of a dynamic page
 * serving. Each subclass implements it's own getContent() function
 * to return a template of the page that would be served. The page
 * template is a String, and the served page, would be dynamically
 * generated using this template. The generation process is the method
 * in which instances of strings in the template are replaced with some
 * dynamically generated values. It is implemented in render()
 * @author avikam
 *
 */
public abstract class HTMLRenderer {
	
	protected abstract String getContent();
	protected HashMap<String, String> replaceMap;
	
	HTMLRenderer() {
		this.replaceMap = new HashMap<String, String>();
		
		this.replaceMap.put("$SERVER$", WorkManager.getInetAddress().toString());
	}
	
	/**
	 * Renders the template. Iterating over the string provided by getContent
	 * and replace instances of replaceMap keys with their corresponding values
	 * @return rendered page
	 */
	public String render() {
		String page = this.getContent();
		for (Entry<String, String> e : this.replaceMap.entrySet()) {
			page = page.replace(e.getKey(), e.getValue());
		}
		
		return page;
	}
	
	public static class UploadedTemplate extends HTMLRenderer {
		private static final String TEMPLATE = "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" + 
		"<head>\n" +
		"<title>$SERVER$/photos/$RESOURCE_ID$</title>\n" +
		"</head>\n" +
		"<body>\n" +
		"<b>HTTP/1.1 201 Created:</b>\n" +
		"<a href=\"/photos/$RESOURCE_ID$\">Resource $RESOURCE_ID$</a>\n" +
		"has been created successfully.<br/>\n" +
		"Original image can be found <a href=\"/photos/$RESOURCE_ID$?rep=0\">here</a>.\n" +
		"</body>\n" +
		"</html>";
		
		UploadedTemplate(int resId) {
			this.replaceMap.put("$RESOURCE_ID$", Integer.toString(resId));
		}

		@Override
		protected String getContent() {
			return UploadedTemplate.TEMPLATE;
		}
	}
	
	
	public static class GetAllPhotosTemplate extends HTMLRenderer {
		private static final String TEMPLATE = 
			"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN" +
			"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>" +
			"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">" +
			"<head>" + 
				"<title>photos</title>" + 
			"</head>" + 
			"<body>" + 
				"<p>Photos</p>" + 
				"<ol>$RESOURCE_LIST$</ol>" + 
			"</body>" + 
			"</html>";
		
		
		/**
		 * C'tor - Create a list HTML view of all representations and resources
		 */
		public GetAllPhotosTemplate() {
			Formatter list = new Formatter();
			
			for (Integer res : WorkManager.jobDisterbutor().getAllResources()) {
				list.format("<li><a href=\"/photos/%d\">Photo %d</a>", res, res);
				list.format("<ol>");
				for (Representation rep : WorkManager.jobDisterbutor().getPresentaionsFor(res)) {
					list.format("<li><a href=\"/photos/%d?rep=%d\">Representation %d</a></li>", 
							res, rep.getId(), rep.getId());
				}
				list.format("</ol>");
			}
			
			this.replaceMap.put("$RESOURCE_LIST$", list.toString());
			
		}
		
		@Override
		protected String getContent() {
			return GetAllPhotosTemplate.TEMPLATE;
		}
		
	}
	public static class GetPhotosTemplate extends HTMLRenderer {
		private static final String TEMPLATE = 
		"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
		"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" +
		"<head>\n" +
			"<title>$SERVER$/photos/$RESOURCE_ID$</title>\n" + 
		"</head>\n" +
		"<body>\n" +
			"<p>JOB STATUS CATEGORY</p>\n" +
			"<ol>\n" +
				"$RESOURCE_LIST$\n" +
			"</ol>\n" +
		"</body>\n" +
		"</html>\n";
		
		
		/**
		 * C'tor - Create a list HTML view of that representations
		 * @param resId is the resource id
		 * @param resourceRepresentations is a list view that hold all representations
		 */
		public GetPhotosTemplate(int resId, List<Representation> resourceRepresentations) {
			try {
				WorkManager.jobDisterbutor().readLock.lock();
				Formatter list = new Formatter();
				for (Representation r : resourceRepresentations) {
					list.format("<li><a href=\"/photos/%d?rep=%d\">Representation %d</a>\n", 
							resId, r.getId(), r.getId());
					
					list.format("<ul>\n");
					
					List<Job> jobs = r.getJobs();
					if (jobs != null) {
						for (Job j : jobs) {
							if (j != null) {
								list.format("<li><a href=\"/jobs/%d\">JOB %d</a>. Status - [%s]</li>\n",
									j.getId(), j.getId(), j.getStatus());
							}
						}
					}
					
					list.format("</ul>\n");
					list.format("</li>\n");
				}			
				this.replaceMap.put("$RESOURCE_ID$", Integer.toString(resId));
				this.replaceMap.put("$RESOURCE_LIST$", list.toString());
			} finally {
				WorkManager.jobDisterbutor().readLock.unlock();
			}
		}

		@Override
		protected String getContent() {
			return GetPhotosTemplate.TEMPLATE;
		}
	}
	
	public static class GetJobsTemplate extends HTMLRenderer {
		private static final String TEMPLATE = 
			"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" + 
			"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + 
			"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" +
			"<head>\n" + 
				"<title>$SERVER$/jobs</title>\n" + 
			"</head>\n" +
			"<body>\n" +
				"<p>Jobs Status</p>\n" +
				"<ol>\n" +
					"<li>Non Submitted Jobs\n" +
						"$NON-SUBMITTED$" +  
				  	"</li>\n" +
				  	"<li>Submitted Jobs\n" +
				  		"$SUBMITTED$" +
	  				"</li>\n" +
					"<li>Finshed Jobs\n" +
						"$FINISHED$" +
				"</li>\n" +
			"</ol>\n" +
		"</body>\n" +
		"</html>\n";
		
		GetJobsTemplate(List<Job> submitted, List<Job> nonSubmitted, List<Job> finished) {
			try {
				WorkManager.jobDisterbutor().readLock.lock();
			
				this.replaceMap.put("$NON-SUBMITTED$", this.getJobTable(nonSubmitted));
				this.replaceMap.put("$SUBMITTED$", this.getJobTable(submitted));
				this.replaceMap.put("$FINISHED$", this.getJobTable(finished));
				
			} finally {
				WorkManager.jobDisterbutor().readLock.unlock();
			}
		}
		
		private String getJobTable(List<Job> jobs) {
			if (null == jobs)
				return "";
			
			Formatter tbl = new Formatter();
			tbl.format("<ul>");
			for (Job j : jobs){
				tbl.format("<li><a href=\"/jobs/%d\">JOB %d</a>:\n<a href=\"/photos/%d\">Resource %d</a>.</li>\n",
		  					j.getId(), j.getId(), j.getResId(), j.getResId());  
			}
			tbl.format("</ul>");
			return tbl.toString();
		}
		
		@Override
		protected String getContent() {
			return GetJobsTemplate.TEMPLATE;
		}
		
	}
	
	public static class GetLinkRepresentationTemplate extends HTMLRenderer {
		private static final String TEMPLATE = 
			"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" + 
			"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + 
			"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" +
			"<head>\n" + 
				"<title>$SERVER$/jobs</title>\n" + 
			"</head>\n" +
			"<body>\n" +
			"<a href=/photos/$RES_ID$?rep=$REP_ID$>link</a>\n" + 
			"</body>\n" +
			"</html>\n";

		GetLinkRepresentationTemplate(int resId, int repId) {			
			this.replaceMap.put("$RES_ID$", Integer.toString(resId));
			this.replaceMap.put("$REP_ID$", Integer.toString(repId));
		}
		
		@Override
		public String getContent() {
			return GetLinkRepresentationTemplate.TEMPLATE;
		}
	}
}
